<?
require_once("ericdingle/model/BaseProvider.php");
require_once("ericdingle/model/photo/PhotoProvider.php");
require_once("ericdingle/model/post/PostEntity.php");
require_once("ericdingle/model/postlabel/PostLabelProvider.php");

class PostProvider extends BaseProvider {
	private static $PAGE_SIZE = 5;
	
	public static function getInstance() {
		return parent::getInstance(__CLASS__);
	}

	// CRUD
	
	public function create($post) {
		$postID = $this->dataInterface_->executeNonQuery(sprintf(
			"INSERT INTO Post (PostID, Title, Date, Content) " .
			"VALUES (NULL, '%s', '%s', '%s')",
			$this->dataInterface_->sanitize($post->getTitle()),
			$post->getDate()->toMySQLStr(),
			$this->dataInterface_->sanitize($post->getContent())
		));
		
		$post->setPostID($postID);
		
		$postLabelProvider = PostLabelProvider::getInstance();
		$postLabelProvider->create($post);
	}
	
	public function read($post = null, $orderBy = null, $limit = null) {
		if (!$orderBy) $orderBy = "P.PostID DESC";
	
		$result = $this->dataInterface_->executeQuery(
			"SELECT P.PostID, P.Title, P.Date, P.Content, " .
				"(SELECT GROUP_CONCAT(PL.LabelID SEPARATOR ',') " .
				 "FROM PostLabel PL " .
				 "WHERE PL.PostID = P.PostID) AS LabelIDs, " .
				"(SELECT PH.Path " .
				 "FROM Photo PH " .
				 "WHERE PH.PostID = P.PostID " .
				 "LIMIT 1) AS Path, " .
				"(SELECT COUNT(C.CommentID) " .
				 "FROM Comment C " .
				 "WHERE C.PostID = P.PostID) AS CommentCount " .
			"FROM Post P " .
			($post ? "WHERE " . $this->getConstraints($post) . " " : "") .
			"ORDER BY $orderBy " .
			($limit ? "LIMIT $limit" : "")
		);
		
		if (!$result) {
			die($this->dataInterface_->getError());
		}
		
		$posts = array();
		while ($row = $this->dataInterface_->getNextRow($result)) {
			array_push($posts, $this->loadEntity($row));
		}
		
		return $posts;
	}
	
	public function update($post) {
		$this->dataInterface_->executeNonQuery(sprintf(
			"UPDATE Post " .
			"SET Title = '%s', Date = '%s', Content = '%s' " .
			"WHERE PostID = %d",
			$this->dataInterface_->sanitize($post->getTitle()),
			$post->getDate()->toMySQLStr(),
			$this->dataInterface_->sanitize($post->getContent()),
			$post->getPostID()
		));
		
		$postLabelProvider = PostLabelProvider::getInstance();
		$postLabelProvider->update($post);
	}
	
	public function delete($post) {
		$postLabelProvider = PostLabelProvider::getInstance();
		$postLabelProvider->delete($post);
		
		$photoProvider = PhotoProvider::getInstance();
		$photoProvider->delete($post);
	
		$this->dataInterface_->executeNonQuery(sprintf(
			"DELETE FROM Post " .
			"WHERE PostID = %d",
			$post->getPostID()
		));
	}
	
	// Helpers

	private function getConstraints($post) {
		$constraints = array();
		if ($postID = $post->getPostID()) {
			array_push($constraints, sprintf("P.PostID = %d", $postID));
		}
		if ($content = $post->getContent()) {
			array_push($constraints, sprintf("P.Content LIKE '%%%s%%' ", $this->dataInterface_->sanitize($content)));
		}
		if (list($labelID) = $post->getLabelIDs()) {
			array_push($constraints, sprintf(
				"EXISTS (SELECT PL2.LabelID FROM PostLabel PL2 WHERE PL2.PostID = P.PostID AND PL2.LabelID = %d)",
				$labelID
			));
		}
		return implode(" AND ", $constraints);
	}
	
	private function getLimitFromPage($page) {
		return ($page - 1) * self::$PAGE_SIZE . "," . self::$PAGE_SIZE;
	}
	
	private function loadEntity($row) {
		return new PostEntity(
			$row["PostID"],
			$row["Title"],
			PostDate::fromMySQLStr($row["Date"]),
			$row["Content"],
			preg_split("/,/", $row["LabelIDs"]),
			$row["Path"] ? new PhotoEntity(null, $row["PostID"], $row["Path"], null) : null,
			$row["CommentCount"]
		);
	}
	
	private function readCount($post = null) {
		return $this->dataInterface_->executeScalar(
			"SELECT count(P.PostID) " .
			"FROM Post P " .
			($post ? "WHERE " . $this->getConstraints($post) : "")
		);
	}
	
	public function readPage($page) {
		return $this->read(null, null, $this->getLimitFromPage($page));
	}
	
	public function readPageCount() {
		return ceil($this->readCount() / self::$PAGE_SIZE);
	}
	
	public function readPageByLabelID($page, $labelID) {
		$post = new PostEntity(null, null, null, null, array($labelID));
		return $this->read($post, null, $this->getLimitFromPage($page));
	}
	
	public function readPageCountByLabelID($labelID) {
		$post = new PostEntity(null, null, null, null, array($labelID));
		$count = $this->readCount($post);
		return ceil($count / self::$PAGE_SIZE);
	}
	
	public function readPageByKeyword($page, $keyword) {
		$post = new PostEntity(null, null, null, $keyword);
		return $this->read($post, null, $this->getLimitFromPage($page));
	}
	
	public function readPageCountByKeyword($keyword) {
		$post = new PostEntity(null, null, null, $keyword);
		$count = $this->readCount($post);
		return ceil($count / self::$PAGE_SIZE);
	}
	
	public function readByPostID($postID) {
		$post = new PostEntity($postID);
		$posts = $this->read($post);
		return $posts[0];
	}
}
?>
